"""
数据库服务类 - 处理用户和第三方登录的数据操作
"""

from tortoise import Tortoise
from tortoise.exceptions import DoesNotExist
from models import User, ThirdPartyLogin, PlatformType, UserStatus, UserType
from typing import Optional, Dict, Any
import hashlib
import secrets
from datetime import datetime, timedelta
import json


class DatabaseService:
    """数据库服务类"""

    @staticmethod
    async def init_db():
        """初始化数据库连接"""
        try:
            # 检查是否已经初始化
            if Tortoise._inited:
                return

            await Tortoise.init(
                db_url='mysql://root:123456@39.107.155.107:3307/paopao',
                modules={'models': ['models']}
            )
            await Tortoise.generate_schemas()
            print("✅ 数据库初始化成功")
        except Exception as e:
            print(f"❌ 数据库初始化失败: {e}")
            raise

    @staticmethod
    async def close_db():
        """关闭数据库连接"""
        await Tortoise.close_connections()

    @staticmethod
    def generate_password_hash(password: str) -> str:
        """生成密码哈希"""
        return hashlib.sha256(password.encode()).hexdigest()

    @staticmethod
    def generate_random_password() -> str:
        """生成随机密码"""
        return secrets.token_urlsafe(16)

    @classmethod
    async def find_user_by_third_party(cls, platform: str, open_id: str) -> Optional[User]:
        """根据第三方平台和OpenID查找用户"""
        try:
            # 确保数据库连接已初始化
            if not Tortoise.get_connection("default"):
                await cls.init_db()

            third_party_login = await ThirdPartyLogin.get(
                platform=platform,
                open_id=open_id
            )
            user = await third_party_login.user
            return user
        except DoesNotExist:
            return None

    @classmethod
    async def find_third_party_login(cls, platform: str, open_id: str) -> Optional[ThirdPartyLogin]:
        """查找第三方登录记录"""
        try:
            # 确保数据库连接已初始化
            if not Tortoise.get_connection("default"):
                await cls.init_db()

            return await ThirdPartyLogin.get(
                platform=platform,
                open_id=open_id
            )
        except DoesNotExist:
            return None

    @classmethod
    async def create_user_from_dingtalk(cls, dingtalk_user: Dict[str, Any]) -> User:
        """从钉钉用户信息创建用户"""
        print(f"🔍 创建用户 - 钉钉用户信息: {dingtalk_user}")

        # 生成用户名和密码
        base_username = dingtalk_user.get('name', '钉钉用户')
        print(f"📝 基础用户名: {base_username}")
        username = await cls._generate_unique_username(base_username)
        password = cls.generate_random_password()
        password_hash = cls.generate_password_hash(password)

        print(f"✅ 最终用户名: {username}")

        # 创建用户
        user = await User.create(
            username=username,
            email=dingtalk_user.get('email'),
            phone=dingtalk_user.get('mobile'),
            password_hash=password_hash,
            avatar=dingtalk_user.get('avatar_url'),
            nickname=dingtalk_user.get('name'),
            bio=f"钉钉用户 - {dingtalk_user.get('name', '')}",
            user_type=UserType.NORMAL,
            status=UserStatus.ACTIVE,
            last_login_at=datetime.now()
        )

        print(f"✅ 用户创建成功: {user.username} (ID: {user.id})")
        return user

    @classmethod
    async def create_third_party_login(cls, user: User, platform: str, dingtalk_user: Dict[str, Any]) -> ThirdPartyLogin:
        """创建第三方登录记录"""
        print(f"🔍 创建第三方登录记录 - 用户: {user.username}, 平台: {platform}")
        print(f"📝 钉钉用户数据: {dingtalk_user}")

        third_party_login = await ThirdPartyLogin.create(
            user=user,
            platform=platform,
            open_id=dingtalk_user.get('id', ''),
            union_id=dingtalk_user.get('unionid'),
            access_token=dingtalk_user.get('access_token', ''),
            expires_at=datetime.now() + timedelta(hours=24)  # 假设24小时过期
        )

        print(f"✅ 第三方登录记录创建成功: {third_party_login.id}")
        return third_party_login

    @classmethod
    async def update_user_login_time(cls, user: User):
        """更新用户最后登录时间"""
        user.last_login_at = datetime.now()
        await user.save()

    @classmethod
    async def _generate_unique_username(cls, base_name: str) -> str:
        """生成唯一的用户名"""
        username = base_name
        counter = 1

        while await cls._username_exists(username):
            username = f"{base_name}{counter}"
            counter += 1

        return username

    @classmethod
    async def _username_exists(cls, username: str) -> bool:
        """检查用户名是否已存在"""
        try:
            # 确保数据库连接已初始化
            if not Tortoise.get_connection("default"):
                await cls.init_db()

            await User.get(username=username)
            return True
        except DoesNotExist:
            return False

    @classmethod
    async def dingtalk_login_or_register(cls, dingtalk_user: Dict[str, Any]) -> Dict[str, Any]:
        """
        钉钉登录或注册处理

        Args:
            dingtalk_user: 钉钉用户信息

        Returns:
            Dict包含用户信息和登录状态
        """
        platform = PlatformType.DINGDING
        open_id = dingtalk_user.get('id', '')

        print(f"🔍 数据库服务处理钉钉用户: {dingtalk_user}")
        print(f"📝 用户ID: {open_id}")

        if not open_id:
            print(f"❌ 钉钉用户ID为空，返回错误")
            return {
                "success": False,
                "error": "钉钉用户ID不能为空"
            }

        print(f"✅ 用户ID验证通过: {open_id}")

        # 1. 先查询是否已有该钉钉用户的记录
        print(f"🔍 查询第三方登录记录: platform={platform}, open_id={open_id}")
        existing_user = await cls.find_user_by_third_party(platform, open_id)

        if existing_user:
            print(f"✅ 找到现有用户: {existing_user.username} (ID: {existing_user.id})")
            # 用户已存在，更新登录时间
            await cls.update_user_login_time(existing_user)

            # 获取第三方登录记录
            third_party_login = await cls.find_third_party_login(platform, open_id)

            return {
                "success": True,
                "message": "钉钉登录成功",
                "user": {
                    "id": existing_user.id,
                    "username": existing_user.username,
                    "nickname": existing_user.nickname,
                    "avatar": existing_user.avatar,
                    "email": existing_user.email,
                    "phone": existing_user.phone,
                    "user_type": existing_user.user_type,
                    "created_at": existing_user.created_at.isoformat() if existing_user.created_at else None,
                    "last_login_at": existing_user.last_login_at.isoformat() if existing_user.last_login_at else None
                },
                "third_party_login": {
                    "platform": third_party_login.platform if third_party_login else platform,
                    "open_id": open_id,
                    "union_id": dingtalk_user.get('unionid'),
                    "created_at": third_party_login.created_at.isoformat() if third_party_login else None
                },
                "is_new_user": False
            }
        else:
            print(f"ℹ️ 用户不存在，准备创建新用户")
            # 用户不存在，创建新用户
            try:
                # 创建用户
                new_user = await cls.create_user_from_dingtalk(dingtalk_user)
                print(f"✅ 新用户创建成功: {new_user.username} (ID: {new_user.id})")

                # 创建第三方登录记录
                await cls.create_third_party_login(new_user, platform, dingtalk_user)
                print(f"✅ 第三方登录记录创建成功")

                return {
                    "success": True,
                    "message": "钉钉注册并登录成功",
                    "user": {
                        "id": new_user.id,
                        "username": new_user.username,
                        "nickname": new_user.nickname,
                        "avatar": new_user.avatar,
                        "email": new_user.email,
                        "phone": new_user.phone,
                        "user_type": new_user.user_type,
                        "created_at": new_user.created_at.isoformat() if new_user.created_at else None,
                        "last_login_at": new_user.last_login_at.isoformat() if new_user.last_login_at else None
                    },
                    "third_party_login": {
                        "platform": platform,
                        "open_id": open_id,
                        "union_id": dingtalk_user.get('unionid'),
                        "created_at": datetime.now().isoformat()
                    },
                    "is_new_user": True
                }
            except Exception as e:
                print(f"❌ 创建用户失败: {e}")
                import traceback
                traceback.print_exc()
                return {
                    "success": False,
                    "error": f"创建用户失败: {str(e)}"
                }

    @classmethod
    async def gitee_login_or_register(cls, gitee_user: Dict[str, Any]) -> Dict[str, Any]:
        """
        Gitee登录或注册处理

        Args:
            gitee_user: Gitee用户信息

        Returns:
            Dict包含用户信息和登录状态
        """
        platform = PlatformType.GITEE
        open_id = gitee_user.get('id', '')

        print(f"🔍 数据库服务处理Gitee用户: {gitee_user}")
        print(f"📝 用户ID: {open_id}")

        if not open_id:
            print(f"❌ Gitee用户ID为空，返回错误")
            return {
                "success": False,
                "error": "Gitee用户ID不能为空"
            }

        print(f"✅ 用户ID验证通过: {open_id}")

        # 1. 先查询是否已有该Gitee用户的记录
        print(f"🔍 查询第三方登录记录: platform={platform}, open_id={open_id}")
        existing_user = await cls.find_user_by_third_party(platform, open_id)

        if existing_user:
            print(f"✅ 找到现有用户: {existing_user.username} (ID: {existing_user.id})")
            # 用户已存在，更新登录时间
            await cls.update_user_login_time(existing_user)

            # 获取第三方登录记录
            third_party_login = await cls.find_third_party_login(platform, open_id)

            return {
                "success": True,
                "message": "Gitee登录成功",
                "user": {
                    "id": existing_user.id,
                    "username": existing_user.username,
                    "nickname": existing_user.nickname,
                    "avatar": existing_user.avatar,
                    "email": existing_user.email,
                    "phone": existing_user.phone,
                    "user_type": existing_user.user_type,
                    "created_at": existing_user.created_at.isoformat() if existing_user.created_at else None,
                    "last_login_at": existing_user.last_login_at.isoformat() if existing_user.last_login_at else None
                },
                "third_party_login": {
                    "platform": third_party_login.platform if third_party_login else platform,
                    "open_id": open_id,
                    "union_id": gitee_user.get('unionid'),
                    "created_at": third_party_login.created_at.isoformat() if third_party_login else None
                },
                "is_new_user": False
            }
        else:
            print(f"ℹ️ 用户不存在，准备创建新用户")
            # 用户不存在，创建新用户
            try:
                # 创建用户
                new_user = await cls.create_user_from_gitee(gitee_user)
                print(f"✅ 新用户创建成功: {new_user.username} (ID: {new_user.id})")

                # 创建第三方登录记录
                await cls.create_third_party_login(new_user, platform, gitee_user)
                print(f"✅ 第三方登录记录创建成功")

                return {
                    "success": True,
                    "message": "Gitee注册并登录成功",
                    "user": {
                        "id": new_user.id,
                        "username": new_user.username,
                        "nickname": new_user.nickname,
                        "avatar": new_user.avatar,
                        "email": new_user.email,
                        "phone": new_user.phone,
                        "user_type": new_user.user_type,
                        "created_at": new_user.created_at.isoformat() if new_user.created_at else None,
                        "last_login_at": new_user.last_login_at.isoformat() if new_user.last_login_at else None
                    },
                    "third_party_login": {
                        "platform": platform,
                        "open_id": open_id,
                        "union_id": gitee_user.get('unionid'),
                        "created_at": datetime.now().isoformat()
                    },
                    "is_new_user": True
                }
            except Exception as e:
                print(f"❌ 创建用户失败: {e}")
                import traceback
                traceback.print_exc()
                return {
                    "success": False,
                    "error": f"创建用户失败: {str(e)}"
                }

    @classmethod
    async def create_user_from_gitee(cls, gitee_user: Dict[str, Any]) -> User:
        """从Gitee用户信息创建用户"""
        print(f"🔍 创建用户 - Gitee用户信息: {gitee_user}")

        # 生成用户名和密码
        base_username = gitee_user.get('login', 'gitee用户')
        print(f"📝 基础用户名: {base_username}")
        username = await cls._generate_unique_username(base_username)
        password = cls.generate_random_password()
        password_hash = cls.generate_password_hash(password)

        print(f"✅ 最终用户名: {username}")

        # 创建用户
        user = await User.create(
            username=username,
            email=gitee_user.get('email'),
            phone=None,  # Gitee没有手机号信息
            password_hash=password_hash,
            avatar=gitee_user.get('avatar_url'),
            nickname=gitee_user.get('name'),
            bio=gitee_user.get('bio', f"Gitee用户 - {gitee_user.get('name', '')}"),
            user_type=UserType.NORMAL,
            status=UserStatus.ACTIVE,
            last_login_at=datetime.now()
        )

        print(f"✅ 用户创建成功: {user.username} (ID: {user.id})")
        return user

    @classmethod
    async def get_user_third_party_logins(cls, user_id: int) -> Dict[str, Any]:
        """获取用户的所有第三方登录信息"""
        try:
            # 确保数据库连接已初始化
            if not Tortoise.get_connection("default"):
                await cls.init_db()

            user = await User.get(id=user_id)
            third_party_logins = await user.third_party_logins

            result = []
            for login in third_party_logins:
                result.append({
                    "id": login.id,
                    "platform": login.platform,
                    "open_id": login.open_id,
                    "union_id": login.union_id,
                    "created_at": login.created_at.isoformat() if login.created_at else None,
                    "updated_at": login.updated_at.isoformat() if login.updated_at else None
                })

            return {
                "success": True,
                "third_party_logins": result
            }
        except DoesNotExist:
            return {
                "success": False,
                "error": "用户不存在"
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"获取第三方登录信息失败: {str(e)}"
            }

    @classmethod
    async def get_database_stats(cls) -> Dict[str, Any]:
        """获取数据库统计信息"""
        try:
            # 确保数据库连接已初始化
            if not Tortoise.get_connection("default"):
                await cls.init_db()

            user_count = await User.all().count()
            third_party_count = await ThirdPartyLogin.all().count()
            dingtalk_count = await ThirdPartyLogin.filter(platform=PlatformType.DINGDING).count()

            return {
                "success": True,
                "stats": {
                    "total_users": user_count,
                    "total_third_party_logins": third_party_count,
                    "dingtalk_logins": dingtalk_count
                }
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"获取统计信息失败: {str(e)}"
            }
